package webjoch.process.strategies.puzzles;

import java.awt.Graphics2D;

import com.rsbuddy.event.events.MessageEvent;
import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Objects;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.task.Task;
import com.rsbuddy.script.util.Filter;
import com.rsbuddy.script.wrappers.GameObject;

import webjoch.methods.Food;
import webjoch.misc.Constants;
import webjoch.misc.Functions;
import webjoch.process.strategies.Puzzle;
import webjoch.wrappers.Door;
import webjoch.wrappers.Room;

/**
 * 
 * @author Webjoch
 *
 */

public class Traps extends Puzzle{
	Room room;
	boolean traverse = false;
	
	private int row1, row2, row3;
	
	private int[] ROW_1 = {49390, 49392, 49394, 49396};
	private int[] ROW_2 = {49398, 49400, 49402, 49404};
	private int[] ROW_3 = {49406, 49408, 49410, 49412};
	private int[][] TRAPS = {ROW_1, ROW_2, ROW_3};
	
	private int[] ROW_1_ALL = {49390, 49391, 49392, 49393, 49394, 49395, 49396};
	private int[] ROW_2_ALL = {49398, 49399, 49400, 49401, 49402, 49403, 49404};
	private int[] ROW_3_ALL = {49406, 49407, 49408, 49409, 49410, 49411, 49412};
	
	@Override
	public void setRoom(Room room) {
		this.room = room;
	}

	@Override
	public boolean isValid(){
		traverse = false;
		GameObject[] traps = Objects.getLoaded(new Filter<GameObject>(){
			public boolean accept(GameObject o) {
				return room.getArea().contains(o.getLocation()) && Functions.inArray(TRAPS, o.getId());
			}
			
		});
		return traps.length > 0;
	}

	@Override
	public Type getType() {
		return Puzzle.Type.TRAPS;
	}

	/**
	 * This puzzle must be solved again when you want to the previous room
	 */
	public void traverse(){
		traverse = true;
	}
	
	@Override
	public int loop(){
		GameObject door = Objects.getNearest(new Filter<GameObject>(){
			public boolean accept(GameObject o){
				return Functions.inArray(Constants.ALL_DOORS, o.getId());
			}
		});
		GameObject trapRow1 = Objects.getNearest(ROW_1_ALL);
		GameObject trapRow2 = Objects.getNearest(ROW_2_ALL);
		GameObject trapRow3 = Objects.getNearest(ROW_3_ALL);
		
		Food.eat();
		if (traverse){
			if (Calculations.distanceTo(trapRow1) < 3 && Calculations.distanceTo(trapRow2) < 3){
				if (row1 == 0){ row1 = tryTraps(ROW_1); }else{ tryTraps(new int[] {row1}); }
			}else if (Calculations.distanceTo(trapRow3) < 3 && Calculations.distanceTo(trapRow2) < 3){
				if (row2 == 0){ row2 = tryTraps(ROW_2); }else{ tryTraps(new int[] {row2}); }
			}else{
				if (row3 == 0){ row3 = tryTraps(ROW_3); }else{ tryTraps(new int[] {row3}); }
			}
		}else{
			if (Calculations.distanceTo(trapRow1) < 3 && Calculations.distanceTo(door) < 3){
				if (row1 == 0){ row1 = tryTraps(ROW_1); }else{ tryTraps(new int[] {row1}); }
			}
			if (Calculations.distanceTo(trapRow1) < 3 && Calculations.distanceTo(trapRow2) < 3){
				if (row2 == 0){ row2 = tryTraps(ROW_2); }else{ tryTraps(new int[] {row2}); }
			}
			if (Calculations.distanceTo(trapRow3) < 3 && Calculations.distanceTo(trapRow2) < 3){
				if (row3 == 0){ row3 = tryTraps(ROW_3); }else{ tryTraps(new int[] {row3}); }
			}
		}
		
		return 0;
	}
	
	/**
	 * Click on the traps
	 * @param objectIds traps to click on
	 * @return the succeed trap
	 */
	public int tryTraps(int[] objectIds){
		o:
		for (int objectId : objectIds){
			if (Objects.getNearest(objectId) == null) continue;
			
			Objects.getNearest(objectId).interact("Step-onto");
			for (int i = 0; i < 100; i++){
				if (Objects.getNearest(objectId) == null){
					Task.sleep(1000);
					continue o;
				}
				Task.sleep(30);
			}
			if (Players.getLocal().getLocation().equals(Objects.getNearest(objectId).getLocation())){
				return objectId;
			}else{
				break;
			}
		}
		return 0;
	}
	
	@Override
	public boolean isFinished() {
		if (traverse){
			GameObject trapRow1 = Objects.getNearest(ROW_1);
			GameObject trapRow2 = Objects.getNearest(ROW_2);
			
			return Calculations.distanceTo(trapRow1) < 3 && Calculations.distanceTo(trapRow2) > 1;
		}
		GameObject trapRow2 = Objects.getNearest(ROW_2);
		GameObject trapRow3 = Objects.getNearest(ROW_3);

		return Calculations.distanceTo(trapRow2) > 1 && Calculations.distanceTo(trapRow3) < Calculations.distanceTo(trapRow2);
	}
	
	/**
	 * Gets the door rotation that the puzzle blocks
	 * @return the blocked door
	 */
	public Door.Rotation getBlockedDoorRotation(){
		for (final Door door : room.getDoors()){
			GameObject[] traps = Objects.getLoaded(new Filter<GameObject>(){
				public boolean accept(GameObject o){
					if (!room.getArea().contains(o.getLocation()) || !Functions.inArray(ROW_1, o.getId())) return false;
					return Calculations.distanceBetween(o.getLocation(), door.getLocation()) < 5;
				}
			});
			if (traps.length > 0) return door.getRotation();
		}
		return null;
	}

	@Override
	public int[] itemNeed() {
		return new int[0];
	}

	@Override
	public void messageReceived(MessageEvent e) {
		
	}

	@Override
	public void onRepaint(Graphics2D g) {
		// TODO Auto-generated method stub
		
	}
}
